#include <atomic>
#include <thread>
#include <iostream>
#include <mutex>
#include <queue>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <condition_variable>
#include <pthread.h>
#include <semaphore.h>
#include <functional>

using namespace std;

std::atomic<int> atomicInt(0); // 使用原子整型，初始值为0


void increment() {
    for (int i = 0; i < 100; ++i) {
        atomicInt++; // 使用原子操作进行自增, 线程安全
    }
    printf("Finish\n");
}

void complexOperations()
{
    printf("start changed\n");

    int oldValue = atomicInt.exchange(50);
    // exchange将atomicInt的值设为50，并返回旧的值

    printf("exchanged: %d\n", atomicInt.load());

    atomicInt.store(25);
    // store将atomicInt的值设为25

    int loadedValue = atomicInt.load();
    // load读取并返回atomicInt的值

    std::cout << "Old value from exchange: " << oldValue << "\n";
    std::cout << "Loaded value: " << loadedValue << "\n";
}


std::atomic<bool> m_runFlag(true);
int count = 0;

void thread1()
{
    printf("Run thread1\n");

    for ( int i=0; i<10; i++ )
    {
        printf("i - %d\n", i);
        std::this_thread::sleep_for(std::chrono::seconds(1));
        if ( i == 5 )
        {
            m_runFlag.store(false);
        }
    }

    printf("Finish Thread1\n");
}

void thread2()
{
    while( m_runFlag.load() )
    {
        printf("waiting......\n");
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    printf("Run thread2\n");
    std::mutex mutex;
    std::lock_guard<std::mutex> glock(mutex);           // 轻锁, 方法结束后自动解锁， 不可手动解锁
    count++;
    printf("Finish Thread2\n");
}


// 两个线程交替给全局变量赋值
std::atomic<int> m_atoNum(0);
std::atomic_flag m_aFlag = ATOMIC_FLAG_INIT;
int thread3(int num)
{
    for ( int i=0; i<8; i++ )
    {
        m_atoNum++;
        printf("thread %d - m_atoNum: %d\n", num, m_atoNum.load());
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    return 0;
}

void thread4(int threadId)
{
    printf("threadId: %d | m_aFlag.state: %d\n", threadId, m_aFlag.test_and_set());

    int i=0;
    while( i< 10 )
    {
        if ( !m_aFlag.test_and_set() )
        {
            i++;
            m_aFlag.clear();
            printf(">>>>>>>threadId: %d | i: %d | m_aFlag.state: %d\n", threadId,  i, m_aFlag.test_and_set());
        }else
        {
            printf("Run Code.\n");
        }
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

std::atomic<bool> ready (false);
std::atomic_flag winner = ATOMIC_FLAG_INIT;

void count1m (int id)
{
  while (!ready) { std::this_thread::yield(); }      // wait for the ready signal
  for (volatile int i=0; i<10; ++i)
  {
        printf("threadId: %d |  i: %d\n", id, i);
        std::this_thread::sleep_for(std::chrono::seconds(1));
  }          // go!, count to 1 million
  if (!winner.test_and_set()) { std::cout << "thread #" << id << " won!\n"; }
};


void fn(int *a)
{
    printf("fn start\n");
    for( int i=0; i<10; i++ )
    {
        std::cout << "num: " << *a << endl;
    }
    printf("fn end\n");
}


std::mutex m_mutex;
std::atomic<bool> m_flag(false);
std::condition_variable m_cv;

void printId(int id)
{
    std::unique_lock<std::mutex> uqLock(m_mutex);

    while(1)
    {
        printf("Wait.....\n");
        m_cv.wait(uqLock);
        printf("To handle something...\n");
    }

//    while( !m_flag.load() )
//        m_cv.wait(uqLock);
    std::cout << "Thread " << id << " Run\n";
}


void go()
{
    std::unique_lock<std::mutex> uqLock(m_mutex);
    m_flag.store(true);
    m_cv.notify_all();
}




char *pBuf = nullptr;

void createBuf(char *buf)
{
    char *pBuf = new char[128];
    buf = pBuf;
}

class Abs
{
public:
    Abs()
    {
        printf("Abs()\n");
    }
    ~Abs()
    {
        printf("~Abs()\n");
    }
};

vector<unique_ptr<Abs>> threadWvec;
vector<unique_ptr<Abs>> thread5vec;

void thread5()
{
    printf("Run %s \n", __FUNCTION__);
    while(1)
    {
        std::unique_lock<std::mutex> uqLock(m_mutex);
        printf("< %s > Wait.....\n", __FUNCTION__);
        m_cv.wait(uqLock);
        printf("< %s > Recv Notify, Print~~~~~~\n", __FUNCTION__);
        for ( int i=0; i<3; i++)
        {
            printf(">>>i: %d\n", i);
            unique_ptr<Abs> ptr(new Abs);
            thread5vec.push_back(std::move(ptr));
        }
    }
}

void thread6()
{
    int count = 0;
    while(1)
    {
        std::unique_lock<std::mutex> uqLock(m_mutex);
        printf("Count: %d\n", count);
        if ( count == 5 )
        {
            printf("Notify...\n");
            m_cv.notify_all();
            uqLock.unlock();
            count = 0;
        }
        count++;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

void threadR(int num)
{
    printf("Run %s | arg: %d\n", __FUNCTION__, num);
    int count = 0;
    while(1)
    {
        std::unique_lock<std::mutex> uniqueLock(m_mutex);
        printf("Cout = %d\n", count);
        if ( count == 5 )
        {
            printf("Send Notify\n");
            m_cv.notify_all();              // 解锁，唤醒全部休眠线程
            uniqueLock.unlock();
            count = 0;
        }
        count++;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

void threadW(int num)
{
    printf("Run %s | arg: %d\n", __FUNCTION__, num);
    while(1)
    {
        printf("[ %s ] Waiting notify......\n", __FUNCTION__);
        std::unique_lock<std::mutex> uniqueLock(m_mutex);
        m_cv.wait(uniqueLock);

        // 执行逻辑代码
        printf("[ %s ] Recv Notify, Print !!!!\n", __FUNCTION__);
        for (int i=0; i<3; i++)
        {
            printf("===i - %d\n", i);
            unique_ptr<Abs> ptr(new Abs);
            threadWvec.push_back(std::move(ptr));
        }
    }
}


class TestAbs
{
public:
    TestAbs(Abs *p, int i)
    {
        m_ptr.reset(p);
        m_num = i;
    }

    void init(int num)
    {
        cout << "===num : " << num << endl;
    }

    void release()
    {
        m_ptr.release();
    }

    TestAbs(){}
    int m_num = 0;
    unique_ptr<Abs> m_ptr = nullptr;
};

typedef std::function<void(int)> func_t;
template<typename T>
void CallTaskFunc(const T&f){
    if(f.operator bool())
    {
        f(1);
    }else{
        std::cout<<"f‘s callable object not set, not callable"<<std::endl;
    }
}


void printNum(int num)
{
    std::cout << "num: " << num << endl;
}

typedef std::function<void()> func_p;

void func(){}

func_p funcPtr()
{
    func_p p = func;
    return p;
}



std::mutex g_mtx; // 全局互斥锁.
std::condition_variable g_cond; // 全局条件变量.
std::deque<int> g_deque;

void consumeFunc(int id)
{
    while (true)
    {
        std::unique_lock <std::mutex> lck(g_mtx);
        std::cout << "thread " << id << " wait..." << endl;

        // 避免虚假唤醒
        g_cond.wait(lck, []{
            return g_deque.size() > 0;
        });

        int aa = g_deque.back();
        std::cout << "thread " << id << "wakeUp | aa:  " << aa << '\n';
        g_deque.pop_back();
        lck.unlock();
    }
}

void produceFunc()
{
    while (true)
    {
        std::unique_lock <std::mutex> lck(g_mtx);
        if (g_deque.empty())
        {
            g_deque.push_back(1);
            g_cond.notify_all(); // 唤醒所有线程.
        }
        lck.unlock();
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

void threadTest(int num)
{
    printf("Num: %d\n", num);
}


int main()
{
    std::thread thread = std::thread(std::bind(threadTest, 3));

    TestAbs ta;
    std::thread threadAbs = std::thread(std::bind(&TestAbs::init, &ta, 3));                 // bind返回函数指针

    auto func = std::bind(&TestAbs::init, &ta, 8);          // 返回function<>类型, 类似函数指针, 可直接调用
    func(8);

    threadAbs.join();
    thread.join();

//    std::thread consumeThread[10];

//    for (int i = 0; i < 10; ++i)
//        consumeThread[i] = std::thread(consumeFunc, i);

//    std::thread produThread;

//    produThread = std::thread(produceFunc);

//    for (int i = 0; i < 10; ++i)
//    {
//        if (consumeThread[i].joinable())
//        {
//            consumeThread[i].join();
//        }
//    }

//    if (produThread.joinable())
//    {
//        produThread.join();
//    }


//    func_t f1;
//    func_t f2 = printNum;

//    CallTaskFunc(f1);
//    CallTaskFunc(f2);

//    // 做返回值
//    func_p fp;
//    func_p ffp = funcPtr;

//    // 打印线程1
//    int num = 1;
//    std::thread threadWrite(threadW, num);

//    // 打印线程2
//    std::thread th5(thread5);

//    num = 2;
//    std::thread threadRead(threadR, num);

//    for ( int i=0; i<5; i++ )
//    {
//        unique_ptr<Abs> ptr(new Abs);
//        threadWvec.push_back(std::move(ptr));
//    }

//    // 使用std::bind绑定类成员函数时，第二个参数要传实参
//    TestAbs tAbs;
//    thread th = std::thread(std::bind(&TestAbs::init, &tAbs, 3));

//    threadRead.join();
//    threadWrite.join();
//    th5.join();
//    th.join();

    return 0;
}
